package com.laker.autotest.common.utils;

import cn.hutool.core.io.FileUtil;
import com.laker.autotest.common.listener.SendEmailListener;
import com.laker.autotest.common.reporters.EasyHtmlEmailReporter;
import com.laker.autotest.common.reporters.EasyHtmlLocalReporter;
import com.laker.autotest.common.retry.RetryAnnotationTransformer;
import lombok.extern.slf4j.Slf4j;
import org.testng.TestNG;
import org.testng.reporters.JUnitReportReporter;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class TestNGUtil {

    public static final String TESTNG_XML = "testng.xml";

    private static String getTestNgXmlPath() {
        try {
            // 直接从类路径获取资源
            java.net.URL url = TestNGUtil.class.getClassLoader().getResource(TESTNG_XML);
            if (url != null) {
                // 如果是文件协议，直接返回路径
                if (url.getProtocol().equals("file")) {
                    return url.getPath();
                }

                // 如果是jar内部资源，需要提取到临时文件
                InputStream testngStream = TestNGUtil.class.getClassLoader().getResourceAsStream(TESTNG_XML);
                if (testngStream != null) {
                    // 在用户目录下创建持久化的目录，避免临时目录被清理的问题
                    String userHome = System.getProperty("user.home");
                    File easyAutoTestDir = new File(userHome, ".easy-auto-test");
                    if (!easyAutoTestDir.exists() && !easyAutoTestDir.mkdirs()) {
                        log.warn("无法创建目录: {}, 将使用临时目录", easyAutoTestDir.getPath());
                        easyAutoTestDir = new File(System.getProperty("java.io.tmpdir"));
                    }

                    File xmlFile = new File(easyAutoTestDir, TESTNG_XML);

                    // 写入文件（如果文件已存在，会被覆盖）
                    FileUtil.writeFromStream(testngStream, xmlFile);
                    log.info("提取 testng.xml 到文件: {}", xmlFile.getPath());
                    return xmlFile.getPath();
                }
            }

            // 如果找不到资源，记录错误并返回null
            log.error("在classpath中找不到 {}", TESTNG_XML);
            return null;
        } catch (Exception e) {
            log.error("获取 testng.xml 路径出错", e);
            return null;
        }
    }

    /**
     * 使用默认的TestNG XML配置文件运行测试
     * 不需要指定源类，直接从当前类加载器获取testng.xml
     */
    public static void runWithTestNgXmlPath() {
        String testNgXmlPath = getTestNgXmlPath();
        log.info("TestNG XML path: {}", testNgXmlPath);
        runWithTestNgXmlPath(testNgXmlPath);
    }

    private static void runWithTestNgXmlPath(String testNgXmlPath) {
        try {
            TestNG testNG = new TestNG(false);
            List<String> config = new ArrayList<>();
            config.add(testNgXmlPath);
            // report
            testNG.setOutputDirectory(TestNGUtil.getReportDir());
            testNG.addListener(new EasyHtmlLocalReporter());
            testNG.addListener(new EasyHtmlEmailReporter());
            // send email
            testNG.addListener(new SendEmailListener());
            // 自定义重试逻辑
            testNG.addListener(new RetryAnnotationTransformer());
            // JUnit report
            testNG.addListener(new JUnitReportReporter());
            testNG.setTestSuites(config);
            testNG.setUseDefaultListeners(false);
            testNG.run();
        } catch (Exception e) {
            log.error("runWithTestNgXmlPath error", e);
        }
    }

    public static String getReportDir() {
        return "report";
    }

    public static String getReportFileName() {
        return "email-report.html";
    }
}
